#pragma once

#include "Market.hpp"
#include "MDDP.hpp"

extern StockMarket::Market market; // defined in main


namespace MDDPMessageParser
{

    static int parse(const MddpMessage::MsgType msg_type,
              MddpMessage::RealTime::MarketData *market_data)
    {
        using MarketData = MddpMessage::RealTime::MarketData;
        using Type = MarketData::Type;
        uint8_t *data = market_data->getExtendFileds();
        switch (msg_type.val())
        {
        case Type::TypeOpeningCallAuctionMarketData:
        { // 集中竞价交易业务行情
            MarketData::OpeningCallAuctionMarketData *opening_call_auction_market_data = (MarketData::OpeningCallAuctionMarketData *)data;
            using MDEntry = MarketData::OpeningCallAuctionMarketData::MDEntry;

            auto no_md_entries = opening_call_auction_market_data->no_md_entries.val();
            MDEntry *md_entry = (MDEntry *)opening_call_auction_market_data->getExtendFileds();

            while (no_md_entries)
            {
                no_md_entries--;

                const int size_of_entry = md_entry->getSelfSize();

                { // process MDEntry
                    char *type = md_entry->md_entry_type;
                    if (type[0] == '2')
                    {
                        market.updateStockPrice(market_data->security_id.val(), md_entry->md_entry_px.val());
                    }
                }

                md_entry = (MDEntry *)((uint8_t *)md_entry + size_of_entry);
            }
            break;
        }
        case Type::TypeAfterHoursBlockTradingMarketData:
        {
            // 盘后定价交易业务行情
            MarketData::AfterHoursBlockTradingMarketData *after_hours_block_trading_market_data = (MarketData::AfterHoursBlockTradingMarketData *)data;
            break;
        }
        case Type::TypeIndexMarketData:
        {
            // 指数行情
            MarketData::IndexMarketData *index_market_data = (MarketData::IndexMarketData *)data;
            break;
        }
        case Type::TypeVolumeStatisticsIndicatorMarketMata:
        {
            // 成交量统计指标行情
            MarketData::VolumeStatisticsIndicatorMarketMata *volume_statistics_indicator_market_mata = (MarketData::VolumeStatisticsIndicatorMarketMata *)data;
            break;
        }
        case Type::TypeRealTimeHongKongStockMarketData:
        {
            // 港股实时行情
            MarketData::RealTimeHongKongStockMarketData *real_time_hong_kong_stock_market_data = (MarketData::RealTimeHongKongStockMarketData *)data;
            break;
        }
        case Type::TypeAfterHoursPricingTradingMarketData:
        {
            // 盘后定价交易业务行情
            MarketData::AfterHoursPricingTradingMarketData *after_hours_pricing_trading_market_data = (MarketData::AfterHoursPricingTradingMarketData *)data;
            break;
        }
        case Type::TypeRealTimeBondSpotTradingMarketData:
        {
            // 债券现货交易实时行情
            MarketData::RealTimeBondSpotTradingMarketData *real_time_bond_spot_trading_market_data = (MarketData::RealTimeBondSpotTradingMarketData *)data;
            break;
        }
        default:
        {
            printf("unknown msg_type: %u\n", msg_type);
            break;
        }
        }
        return 0;
    }

    int parse(uint8_t *buf, uint32_t buf_len)
    {
        const uint8_t *end = buf + buf_len;
        while (buf < end)
        {
            // [msgheader + msg + msg tail/checksum]
            MddpMessage::Header *header = (MddpMessage::Header *)buf;
            uint8_t *data = buf + sizeof(MddpMessage::Header);
            const uint32_t msg_len = (header->msg_len).val();

            const MddpMessage::MsgType msg_type = (header->msg_type);
            switch (msg_type.val())
            {
            case MddpMessage::MessageType::LogOn:
            {
                MddpMessage::Manage::LogOn *logon = (MddpMessage::Manage::LogOn *)data;

                break;
            }
            case MddpMessage::MessageType::Logout:
            {
                MddpMessage::Manage::Logout *logout = (MddpMessage::Manage::Logout *)data;
                break;
            }
            case MddpMessage::MessageType::Heartbeat:
            {
                MddpMessage::Common::Heartbeat *heartbeat = (MddpMessage::Common::Heartbeat *)data;
                break;
            }
            case MddpMessage::MessageType::ChannelHeartbeat:
            {
                MddpMessage::Common::ChannelHeartbeat *channel_heartbeat = (MddpMessage::Common::ChannelHeartbeat *)data;
                break;
            }
            case MddpMessage::MessageType::ResendRequest:
            {
                MddpMessage::Common::ResendRequest *resend_request = (MddpMessage::Common::ResendRequest *)data;
                break;
            }
            // UserInfoReportInfo
            case MddpMessage::MessageType::UserInfoReportInfo:
            {
                MddpMessage::Common::UserInfoReportInfo *user_info_report_info = (MddpMessage::Common::UserInfoReportInfo *)data;
                break;
            }
            // SnapshotMarketChannelStatics
            case MddpMessage::MessageType::SnapshotMarketChannelStatics:
            {
                MddpMessage::Common::SnapshotMarketChannelStatics *snapshot_market_channel_statics = (MddpMessage::Common::SnapshotMarketChannelStatics *)data;
                break;
            }
            // BusinessRejectInfo
            case MddpMessage::MessageType::BusinessRejectInfo:
            {
                MddpMessage::Common::BusinessRejectInfo *business_reject_info = (MddpMessage::Common::BusinessRejectInfo *)data;
                break;
            }
            // TradingSessionInfo
            case MddpMessage::MessageType::TradingSessionInfo:
            {
                MddpMessage::RealTime::TradingSessionInfo *trading_session_info = (MddpMessage::RealTime::TradingSessionInfo *)data;
                break;
            }
            // SecurityInfo
            case MddpMessage::MessageType::SecurityInfo:
            {
                MddpMessage::RealTime::SecurityInfo *security_info = (MddpMessage::RealTime::SecurityInfo *)data;
                break;
            }
            // newsinfo
            case MddpMessage::MessageType::NewsInfo:
            {
                MddpMessage::RealTime::NewsInfo *news_info = (MddpMessage::RealTime::NewsInfo *)data;
                break;
            }
            default:
                if (msg_type.val() / (int)(1e5) == 3)
                {
                    if (msg_type.val() % 100 == 11)
                    {
                        MddpMessage::RealTime::MarketData *market_data = (MddpMessage::RealTime::MarketData *)data;
                        return parse(msg_type, market_data);
                    }
                    else if (msg_type.val() % 100 == 92)
                    {
                    }
                    else if (msg_type.val() % 100 == 91)
                    {
                    }
                    else
                    {
                        // printf("unknown msg_type: %d\n", msg_type.val());
                        return -1;
                    }
                }
                else
                    // printf("unknown msg_type: %d\n", msg_type.val());
                    return -1;
                break;
            }

            buf += msg_len + sizeof(MddpMessage::Header);
        }
        return 0;
    }
} // namespace MDDPMessageParser
